﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using SenerPro;

namespace MensUnoShop.Models
{
    [Serializable]
    public class Order : SimpleOrder
    {
        private Guid _oguid;
        private Guid _mguid;
        private Guid _scguid;
        private string _cashid;
        private List<OrderStatus> _statuslist;
        private List<OrderMarket> _mlist;
        private List<ITradeInDiscount> _dsklist;
        private List<SalesKit> _skgiftlist;
        private int _deliverycost;
        private int _totalprice;//訂單(商品)總金額
        private int _payprice;//實際付款金額(ex:+手續費 +運費 -信用卡紅利, -行銷機制)
        private string _note;
        private string _paywaydetail;
        private string _paywayrequest;
        private int _mcid;
        private int _shippingway;
        private Dictionary<int, int[]> _delivercosttable;
        private Recipient _recipient;
        private byte _invoicetype;
        private string _invoicetitle;
        private string _invoiceserial;

        [NonSerialized]
        private Logger _log;
        [NonSerialized]
        private DBOrder _repository;

        public Guid OGUID { private set { _oguid = value; } get { return _oguid; } }
        public Guid MGUID { set { _mguid = value; } get { return _mguid; } }
        public Guid SCGUID { set { _scguid = value; } get { return _scguid; } }
        public string CASHID { set { _cashid = value; } get { return _cashid; } }
        public List<OrderStatus> STATUSLIST { private set { _statuslist = value; } get { return _statuslist; } }
        public List<OrderMarket> MLIST { set { _mlist = value; } get { return _mlist; } }
        public List<ITradeInDiscount> DSKLIST { set { _dsklist = value; } get { return _dsklist; } }
        public List<SalesKit> SKGIFTLIST { set { _skgiftlist = value; } get { return _skgiftlist; } }
        public int DELIVERYCOST { set { _deliverycost = value; } get { return _deliverycost; } }
        public int TOTALPRICE { set { _totalprice = value; } get { return _totalprice; } }
        public int PAYPRICE { set { _payprice = value; } get { return _payprice; } }
        public string NOTE { set { _note = value; } get { return _note; } }
        public string PAYWAREQUEST { set { _paywayrequest = value; } get { return _paywayrequest; } }
        public string PAYWAYDETAIL { set { _paywaydetail = value; } get { return _paywaydetail; } }
        public Recipient RECIPIENT { set { _recipient = value; } get { return _recipient; } }
        public int MCID { set { _mcid = value; } get { return _mcid; } }
        public int SHIPPINGWAY { set { _shippingway = value; } get { return _shippingway; } }
        public byte INVOICETYPE { set { _invoicetype = value; } get { return _invoicetype; } }
        public string INVOICETITLE { set { _invoicetitle = value; } get { return _invoicetitle; } }
        public string INVOICESERIAL { set { _invoiceserial = value; } get { return _invoiceserial; } }
        public Order()
        {
            _statuslist = new List<OrderStatus>(); 
            _dsklist = new List<ITradeInDiscount>();
        }
        public Order(Guid oguid):base() { _oguid = oguid; }


        [Serializable]
        [DataContract]
        public class OrderStatus
        {
            [DataMember(Order = 1)]
            public Config.OrderStatusType Ostatus { set; get; }
            [DataMember(Order = 2)]
            public DateTime Ochangedate { set; get; }
        }

        //[Serializable]
        //[DataContract]
        //public class ShippingStatus
        //{
        //    [DataMember(Order = 1)]
        //    public Config.ShippingStatusType Ostatus { set; get; }
        //    [DataMember(Order = 2)]
        //    public DateTime Ochangedate { set; get; }
        //}

        public void SetDeliveryCost(string selarea)
        {
            _delivercosttable = new Dictionary<int, int[]>();
            _delivercosttable.Add(2000, new int[] { 0, 500, 700, 930 });
            _delivercosttable.Add(4000, new int[] { 0, 700, 980, 1290 });
            _delivercosttable.Add(6000, new int[] { 0, 850, 1260, 1650 });
            _delivercosttable.Add(8000, new int[] { 0, 1130, 1780, 2370 });
            _delivercosttable.Add(10000, new int[] { 0, 1270, 2040, 2730 });
            _delivercosttable.Add(100000, new int[] { 0, 1410, 2300, 3090 });

            _shippingway = int.Parse(selarea);

            var dt = _delivercosttable.OrderBy(dd => dd.Key).FirstOrDefault(dd => _mlist.Sum(m => m.PRICE) <= dd.Key);
            _deliverycost = dt.Value[_shippingway];
        }

        public void Cal()
        {
            _totalprice = _mlist.Sum(m => m.PRICE);
            _payprice = _totalprice + _deliverycost - _dsklist.Sum(d => d.DEPRICE);
        }

        public bool CheckStock()
        {
            setRepository();
            return _repository.CheckStock(_scguid, _mlist);
        }

        /// <summary>
        /// 取得新訂單編號
        /// </summary>
        public void GetTxid()
        {
            setRepository();
            char[] units = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
            char[] mons = new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C' };
            char year = units[((DateTime.Now.Year) % 26)];
            char month = mons[(DateTime.Now.Month - 1)];
            string day = DateTime.Now.Day.ToString().PadLeft(2, '0');
            Random r = new Random();
            char rand = r.Next(9).ToString()[0];
            _txid = _repository.GetTxId(year, month, day, rand);
        }

        private void setRepository()
        {
            if (_repository == null)
                _repository = new DBOrder();
            if (_log == null)
                _log = new Logger(Config.logpath);
        }

        public bool SaveToDatabase(bool isnew)
        {
            bool isok = false;
            try
            {
                if (isnew)
                {
                    //將購物賣場和購物商品的PK換新，避免購物車重複結帳
                    foreach (var m in _mlist)
                    {
                        m.MOKGUID = Guid.NewGuid();
                    }
                    isok = _repository.CreateOrder(this);
                }
                else
                {
                    isok = _repository.UptOrder(OGUID, CASHID);
                    /*
                    string detail = PAYWAYDETAIL ?? "";
                    detail = bf.Encrypt(detail, Tools.key);
                    string request = bf.Encrypt(PAYWAREQUEST ?? "", Tools.key);
                    isok = _repository.UptOrder(OGUID, CASHID, detail, request, PAYPRICE, NOTE);
                     */
                }
            }
            catch (Exception ex)
            {
                _log = new Logger(Config.logpath);
                _log.RecordException(_log.DBExceptionPath, "[SaveToDatabase]" + ex.ToString());
            }
            return isok;
        }

        /// <summary>
        /// 設定訂單折扣原因及折扣金額
        /// </summary>
        /// <param name="salesKitType"></param>
        /// <param name="deprice"></param>
        /// <param name="detitle"></param>
        public void SetDiscount(Config.OrderDiscountType discountType, int deprice, string detitle)
        {
            setRepository();
            _repository.SetDiscount(_oguid, discountType, deprice, detitle);
        }

        /// <summary>
        /// 取出該筆訂單的折扣項目及金額
        /// </summary>
        public void GetSimpleDiscount()
        {
            setRepository();
            _dsklist = _repository.GetDiscount(_oguid);
        }

        public void Commit()
        {
            setRepository();
            _repository.CommitStock(SCGUID, OGUID);
        }

        public void SaveToTemp()
        {
            byte[] orderbinary = Tools.BinarySerialize(this);
            _repository.SaveTempOrder(CASHID, orderbinary);
        }

        public void FreeStock()
        {
            setRepository();
            _repository.FreeStock(_scguid);
        }

        public void SetStatus(Config.OrderStatusType newstatus)
        {
            setRepository();
            _repository.SetStatus(_oguid, newstatus);
            if (_statuslist != null)
                _statuslist.Add(new OrderStatus() { Ostatus = newstatus, Ochangedate = DateTime.Now });
            else
            {
                _statuslist = new List<OrderStatus>();
                _statuslist.Add(new OrderStatus() { Ostatus = newstatus, Ochangedate = DateTime.Now });
            }
        }

        public void GetStatus()
        {
            setRepository();
            _statuslist = _repository.GetStatus(_oguid);
            STATUS = _statuslist.OrderByDescending(s => s.Ochangedate).First().Ostatus;
        }

        public void GetOrderMarketList()
        {
            setRepository();
            _mlist = _repository.GetOrderMarketList(_oguid);
        }

        public void GetRecipient()
        {
            setRepository();
            _recipient = _repository.GetRecipient(_oguid);
        }

        
    }
}
